package com.geodroid.euclidian;


import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PointF;
import android.util.Log;

import com.geodroid.common.kernel.geos.GeoElement;
import com.geodroid.common.kernel.geos.GeoPoint2;
import com.geodroid.common.kernel.geos.GeoSegment;



public class EuclidianView {
	
	private static final String TAG = "EuclidianView";
	
	private DrawableList allDrawableList = new DrawableList();
	
	public static final double XZERO_STANDARD = 0;
	/** default screen y-coord of origin*/
	public static final double YZERO_STANDARD = 0;
	public static final double XSCALE_STANDARD = 1;
	/** default screen y-coord of origin*/
	public static final double YSCALE_STANDARD = 1;
	
	private double xZero;

	private double yZero;

	private double xscale;

	private double yscale;

	private double invXscale;

	private double invYscale;
	
	
	
	
	
	/**
	 * 
	 */
	public EuclidianView() {
		super();
		xZero = XZERO_STANDARD ; 
		yZero = YZERO_STANDARD ;
		xscale = XSCALE_STANDARD ; 
		yscale = YSCALE_STANDARD ; 
		invXscale = 1 ; 
		invYscale = 1 ;
	}
	/**
	 * adds a GeoPoint to this view
	 */
	public void addPoint(GeoPoint2 gp) {
		Log.d(TAG,"<addPoint>") ; 
		// G.Sturr 2010-6-30
		// filter out any geo not marked for this view
//		IF (!ISVISIBLEINTHISVIEW(GEO)) {
//			RETURN;
			// END G.STURR
//		}

		// check if there is already a drawable for geo
//		Drawable d = getDrawable(geo);
		
//		if (d != null) {
//			return;
//		}

//		d = createDrawable(geo);
		Drawable d = new DrawPoint(gp, this) ;
		if (d != null) {
			addToDrawableLists((Drawable) d);
//			repaint(canvas);
		}
		Log.d(TAG,"</addPoint>") ; 

	}
	public void addSegment(GeoSegment s) {
		// TODO Auto-generated method stub
		Drawable d = new DrawSegment(s, this) ;
		addToDrawableLists((Drawable) d);
	}
	/**
	 * adds a GeoElement to this view
	 * 
	 * @param draw
	 *            drawable to be added
	 */
	protected void addToDrawableLists(Drawable draw) {
		Log.d(TAG,"<addToDrawableLists>") ; 
		if (draw == null) {
			return;
		}
		Drawable d = draw;
		GeoElement geo = d.getGeoElement();
//		int layer = geo.getLayer();
//
//		switch (geo.getGeoClassType()) {
//
//		case ANGLE:
//			if (geo.isIndependent()) {
//				drawLayers[layer].add(d);
//			} else {
//				if (geo.isDrawable()) {
//					drawLayers[layer].add(d);
//				} else {
//					d = null;
//				}
//			}
//			break;
//
//		case IMAGE:
//			if (!bgImageList.contains(d)) {
//				drawLayers[layer].add(d);
//			}
//			break;
//
//		default:
//			drawLayers[layer].add(d);
//			break;
//
//		}

		if (d != null) {
			allDrawableList.add(d);
		}
		Log.d(TAG,"</addToDrawableLists>") ; 
	}
	
	/**
	 * @return the xZero
	 */
	public double getxZero() {
		return xZero;
	}

	/**
	 * @param xZero the xZero to set
	 */
	public void setxZero(double xZero) {
		this.xZero = xZero;
	}

	/**
	 * @return the yZero
	 */
	public double getyZero() {
		return yZero;
	}

	/**
	 * @param yZero the yZero to set
	 */
	public void setyZero(double yZero) {
		this.yZero = yZero;
	}

	/**
	 * @return the xscale
	 */
	public double getXscale() {
		return xscale;
	}

	/**
	 * @param xscale the xscale to set
	 */
	public void setXscale(double xscale) {
		this.xscale = xscale;
		this.invXscale = 1/xscale ;
	}

	/**
	 * @return the yscale
	 */
	public double getYscale() {
		return yscale;
	}

	/**
	 * @param yscale the yscale to set
	 */
	public void setYscale(double yscale) {
		this.yscale = yscale;
		this.invYscale = 1/yscale ;
	}
	
	public double getInvXscale() {
		return invXscale;
	}

	public double getInvYscale() {
		return invYscale;
	}
	/**
	 * @return the allDrawableList
	 */
	public DrawableList getAllDrawableList() {
		return allDrawableList;
	}

	/**
	 * @param allDrawableList the allDrawableList to set
	 */
	public void setAllDrawableList(DrawableList allDrawableList) {
		this.allDrawableList = allDrawableList;
	}

	/**
	 * convert real world coordinate x to screen coordinate x
	 * 
	 * @param xRW real world x coord
	 * @return screen equivalent of real world x-coord
	 */
	final public int toScreenCoordX(double xRW) {
		return (int) Math.round(getxZero() + (xRW * getXscale()));
	}

	/**
	 * convert real world coordinate y to screen coordinate y
	 * 
	 * @param yRW real world y coord
	 * @return screen equivalent of real world y-coord
	 */
	final public int toScreenCoordY(double yRW) {
		return (int) Math.round(getyZero() - (yRW * getYscale()));
	}

	/**
	 * convert real world coordinate x to screen coordinate x
	 * 
	 * @param xRW real world x-coord
	 * @return screen equivalent of real world x-coord as double
	 */
	final public double toScreenCoordXd(double xRW) {
		return getxZero() + (xRW * getXscale());
	}

	/**
	 * convert real world coordinate y to screen coordinate y
	 * 
	 * @param yRW real world y-coord
	 * @return screen equivalent of real world y-coord
	 */
	final public double toScreenCoordYd(double yRW) {
		return getyZero() - (yRW * getYscale());
	}
	
	/**
	 * convert screen coordinate x to real world coordinate x
	 * 
	 * @param x screen coord
	 * @return real world equivalent of screen x-coord
	 */
	final public double toRealWorldCoordX(double x) {
		return (x - getxZero()) * getInvXscale();
	}

	/**
	 * convert screen coordinate y to real world coordinate y
	 * 
	 * @param y screen coord
	 * @return real world equivalent of screen y-coord
	 */
	final public double toRealWorldCoordY(double y) {
		return (getyZero() - y) * getInvYscale();
	}
	
	/**
	 * Draws all objects
	 * @param canvas graphics
	 */
	protected void drawObjects(Canvas canvas) {

		drawGeometricObjects(canvas);
//		drawActionObjects(g2);
//
//		if (previewDrawable != null) {
//			previewDrawable.drawPreview(g2);
//		}
	}

	protected void drawGeometricObjects(Canvas canvas) {
		allDrawableList.drawAll(canvas) ; 
	}
	
	final public void repaint(Canvas canvas) {
		paint(canvas); 
	}
	/**
	 * Paints content of this view.
	 * @param canvas graphics
	 */
	final public void paint(Canvas canvas) {
//		Log.d(TAG,"<paint>" );
		//Graphics2D g2 = (Graphics2D) g;
		// lastGraphics2D = g2;

//		setDefRenderingHints(g2);
		// g2.setClip(0, 0, width, height);

		// BACKGROUND
		// draw background image (with axes and/or grid)
//		if (bgImage == null) {
//			if (firstPaint) {
//				if ((getWidth() > 1) && (getHeight() > 1) && (!reIniting)) {
//					// only set firstPaint to false if the bgImage was generated
//					updateSize();
//					paintBackground(g2);
//					//g2.drawImage(bgImage, 0, 0, null);
//					firstPaint = false;
//				} else {
//					drawBackgroundWithImages(g2);
//				}
//			} else {
//				drawBackgroundWithImages(g2);
//			}
//		} else {
			paintBackground(canvas);
			// draw equations, checkboxes and all geo objects
			drawObjects(canvas);
//		}
//			Log.d(TAG,"</paint>" );
	
}

	private void paintBackground(Canvas canvas) {	
		canvas.drawColor(Color.WHITE) ;
	}
	public void scroll(float u, float v) {
		this.xZero += u ; 
		this.yZero += v ;
	}
	public void zoom(PointF mid, float scale) {
		// TODO Auto-generated method stub
		Log.d(TAG,"Milieu = "+mid.x+","+mid.y) ;
		Log.d(TAG,"Zero = "+xZero+","+yZero) ;
		Log.d(TAG,"ViewScalX = "+xscale) ;
		Log.d(TAG,"ViewScalY = "+yscale) ;
		float xM = mid.x ; 
		float yM = mid.y ;
		this.setXscale(scale*this.xscale) ; 
		this.setYscale(scale*this.yscale) ;
		this.setxZero(xM+scale*(xZero-xM)) ; 
		this.setyZero(yM+scale*(yZero-yM)) ;
	}
	public void scale(float scale) {
		// TODO Auto-generated method stub
		float xM = 300; 
		float yM = 400 ;
		this.setxZero(xM+(scale)*(xZero-xM)) ; 
		this.setyZero(yM+(scale)*(yZero-yM)) ;
		this.setXscale(this.xscale*scale) ; 
		this.setYscale(this.yscale*scale) ;
	}



}
